package gather

/**
  通讯模块
*/
import (
	"bytes"
	"encoding/binary"
	"fmt"
	"github.com/labstack/gommon/log"
	"net"
	"time"
)

/**
  常量
*/
const (
	FrameStartFlag           = 0x68
	FrameTypeTransferDataCmd = 0x85
	FrameTypeReceiveData     = 0x82 //BC 采集数据
	FrameTypeReceiveDataCmd  = 0x85 //BC CMD数据
)

/**
 *
 */
func HeartCmd() []byte {
	var msg TcpProtocolMsg
	msg.FrameStart = FrameStartFlag
	msg.FrameLen = 0x15
	msg.FrameCtrl = 0
	msg.FrameFlag = FrameTypeTransferDataCmd
	msg.FrameCsSt = 0x1
	msg.FrameBeca = 0x1 //0x10;循环、周期
	msg.FrameAppAddr = 0
	msg.FrameInfoAddr = [3]uint8{0x1, 0, 0}
	msg.FrameInfoLen = 0x6
	t := time.Now()
	msg.FrameData = []int8{int8(t.Year() - 2000), int8(t.Month()), int8(t.Day()), int8(t.Hour()), int8(t.Minute()), int8(t.Second())}
	bindata := []byte{}
	pck := &Pack{}
	bindata = pck.Unpack(&msg)
	for i := 0; i < len(bindata); i++ {
		bindata[i] = bindata[i] + 0x33
	}
	//fmt.Printf("%#x", bindata)
	return bindata
}

/**
  建立与C-BMS通讯的服务器
*/
const (
	port = ":8888"
)

func CBmsServer() {
	//建立服务器
	tcpServer, _ := net.ResolveTCPAddr("tcp4", port)
	listener, _ := net.ListenTCP("tcp", tcpServer)
	for {
		conn, err := listener.Accept()
		if err != nil { //监听异常处理
			fmt.Println(err)
			continue
		}
		go handle(conn)

	}

}

const (
	MaxSizePerPacket     = 2048 //每帧的最大数据量
	MaxDataSizePerPacket = 1024 //数据最大量
	FrameHeadLen         = 18   //报文头长度
)

func handle(conn net.Conn) {
	//defer conn.Close() //发生异常把连接断开
	fmt.Println(conn.RemoteAddr())

	n, err := conn.Write(HeartCmd())
	if err != nil {
		println(err)
	}

	buffer := make([]byte, MaxSizePerPacket)
	n, err = conn.Read(buffer)
	if err != nil {
		println(err)
	}
	for i := 0; i < n; i++ {
		buffer[i] -= 0x33
		//fmt.Printf("%#x    ", buffer[i])
	}
	var packetNo uint8 = 0
	dataInfoLen := len(FrameAnalysis(buffer, uint16(n), packetNo))
	for dataInfoLen == MaxDataSizePerPacket { //没有到达最后一包数据
		packetNo += 1
		buffer := FrameHeartAckSend(packetNo)

		n, err = conn.Write(buffer[0:(len(buffer) - 2)])
		buffer = make([]byte, MaxSizePerPacket)
		n, err = conn.Read(buffer)
		//println(packetNo ,"   ")
		for i := 0; i < n; i++ {
			buffer[i] -= 0x33
			//fmt.Printf("%#x    ", buffer[i])
		}
		dataInfoLen = len(FrameAnalysis(buffer, uint16(n), packetNo))
		println(dataInfoLen)
	}

}

const (
	FrameInformationType uint8 = 0x81 //表示发送的是C-BMS的实时数据
	FrameCmdType         uint8 = 0x93 //表示发送的为命令数据
)

/**
 * 对报文进行有效性验证
 */
func FrameAnalysis(byteArr []byte, dataLen uint16, currentPacketNo uint8) []int8 {
	pck := &Pack{}
	msg := pck.PackHead(byteArr)

	if (dataLen < FrameHeadLen-3) || //数据长度小于帧头长度-3（帧标志、帧实际数据长度）
		(msg.FrameStart != FrameStartFlag) ||
		((msg.FrameFlag != FrameTypeReceiveData) && (msg.FrameFlag != FrameTypeReceiveDataCmd)) ||
		(msg.FrameLen != dataLen-3) {
		log.Debug("C-BMS帧格式错误")
		return nil
	}

	infoType := msg.FrameInfoAddr[0]
	//fmt.Printf("%#x", infoType)
	switch infoType {
	case FrameInformationType: //采样数据
		packetNo := msg.FrameInfoAddr[1] //包号
		if currentPacketNo != packetNo { //发送的包号与接受的包号不一致
			log.Debug("当前包号与需要的包号不一致")
			return nil
		}
		dataLen := msg.FrameInfoLen
		msg.FrameData = make([]int8, dataLen)
		binary.Read(bytes.NewReader(byteArr[FrameHeadLen:]), binary.LittleEndian, &msg.FrameData)
		//fmt.Printf("%#x    ", msg.FrameData[0])
		return msg.FrameData

	case FrameCmdType: //命令数据
		fmt.Println("dddddddddddddddddddddddddddddddd")
	default:
		log.Debug("数据类型：", infoType, "无法识别")
		return nil
	}
	return nil
}

/**
 * 发送确认帧，并请求下一包数据
 */
func FrameHeartAckSend(nextPacketNo uint8) []byte {
	var msg TcpProtocolMsg
	msg.FrameStart = FrameStartFlag
	msg.FrameLen = 0xd
	msg.FrameCtrl = 0
	msg.FrameFlag = FrameTypeTransferDataCmd
	msg.FrameCsSt = 0x1
	msg.FrameBeca = 0x1 //0x10;循环、周期
	msg.FrameAppAddr = 0
	msg.FrameInfoAddr = [3]uint8{0x12, nextPacketNo, 0}
	msg.FrameInfoLen = 0
	bindata := []byte{}
	pck := &Pack{}
	bindata = pck.Unpack(&msg)
	for i := 0; i < len(bindata); i++ {
		bindata[i] = bindata[i] + 0x33
	}
	//fmt.Printf("%#x", bindata)
	return bindata
}
